﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Project.Model;
using Project.View;
using Project.UserControls;
using System.Drawing;

namespace Project.Controller
{
    public class Spel : SpelObserver, SpelObservable
    {
        private Speler[] spelers;
        private Bord bord;
        private Dobbelsteen dobbelsteen;
        private SpelUserControlObserver observer;

        private string status;
        
        private int huidigeSpeler;
        private int worp;

        private Log log;

        public Spel(Speler[] spelers)
        {
            this.spelers = spelers;
            this.bord = new Bord(this.spelers);
            for (int i = 0; i < this.spelers.Count(); i++)
            {
                this.spelers[i].RegisterObserver(this);
            }
            this.dobbelsteen = new Dobbelsteen();
        }

        public void RegisterObserver(SpelUserControlObserver o)
        {
            this.observer = o;
        }

        public void start()
        {
            this.huidigeSpeler = gooiEersteSpeler();
            this.getHuidigeSpeler().Pionnen[0].Move = true;
            this.getHuidigeSpeler().VerplaatsPion(this.getHuidigeSpeler().Pionnen[0]);
            this.status = this.getHuidigeSpeler().Naam + " is aan de beurt.";
            this.log.trace(this.getHuidigeSpeler().Naam + " is aan de beurt.");
        }

        // UpdateBord van Spel UserControl
        public void UpdateBord()
        {
            this.observer.UpdateBord();
        }

        public void UpdateGooiButton(bool enable)
        {
            this.observer.UpdateGooiButton(enable);
        }

        public void UpdateDiceImage()
        {
            this.observer.UpdateDiceImage();
        }

        // Gooi 
        public int gooiEersteSpeler()
        {
            List<int> list = new List<int>();
            for (int i = 0; i < this.spelers.Count(); i++)
            {
                list.Add(i);
            }

            while (list.Count() > 1)
            {
                int maxGooi = -1;
                List<int> newList = new List<int>();
                for (int i = 0; i < list.Count(); i++)
                {
                    int gooi = this.dobbelsteen.gooi();
                    if (gooi == maxGooi)
                    {
                        maxGooi = gooi;
                        newList.Add(list[i]);
                    }
                    else if (gooi > maxGooi)
                    {
                        maxGooi = gooi;
                        newList.Clear();
                        newList.Add(list[i]);
                    }
                }
                list = newList;
            }
            return list[0];
        }

        public void PionVerzet(bool nogEenKeer)
        {
            if (!nogEenKeer && this.worp < 6)
            {
                eindeBeurt();
            }
            else
            {
                this.status = "U mag nog een keer gooien.";
                if (this.getHuidigeSpeler() is Bot)
                {
                    this.bot_Gooi();
                }
                else
                {
                    this.UpdateGooiButton(true);
                }
            }
            if (!this.Log.LogOnly)
            {
                this.UpdateBord();
            }
        }

        // Einde Beurt
        public void eindeBeurt()
        {
            if (this.getHuidigeSpeler().isWinnaar())
            {
                ((GUI)this.observer.getForm()).WinnaarScherm(this.getHuidigeSpeler().Naam, this.getHuidigeSpeler().Color);
                this.log.trace(this.getHuidigeSpeler().Naam + " is de winnaar.");
                this.log.Visible = false;
                ((GUI)this.observer.getForm()).Visible = true;
            }
            else
            {
                if (this.huidigeSpeler == this.spelers.Count() - 1)
                {
                    this.huidigeSpeler = 0;
                }
                else
                {
                    this.huidigeSpeler++;
                }
                if (this.getHuidigeSpeler() is Bot)
                {
                    this.bot_Gooi();
                }
                else
                {
                    this.UpdateGooiButton(true);
                }
                if (!this.Log.LogOnly)
                {
                    this.status = "Einde beurt. " + this.getHuidigeSpeler().Naam + " is aan de beurt.";
                    this.UpdateBord();
                }
            }
        }

        public void bot_Gooi()
        {
            this.worp = this.dobbelsteen.gooi();
            this.log.trace(this.getHuidigeSpeler().Naam + " (" + ((Bot)this.getHuidigeSpeler()).getMoeilijkheid() + ") gooide " + this.worp);
            int mogelijkeVakken = this.getHuidigeSpeler().setMogelijkeVakken(this.worp);
            ((Bot)this.getHuidigeSpeler()).berekenZet(mogelijkeVakken);
        }

        public void gooi()
        {
            this.worp = this.dobbelsteen.gooi();
            int mogelijkeVakken = this.getHuidigeSpeler().setMogelijkeVakken(this.worp);
            this.UpdateGooiButton(false);
            if (mogelijkeVakken <= 0)
            {
                eindeBeurt();
                this.status = "U gooide " + this.worp + ". \n U kunt geen pion verplaatsen. \n " + this.getHuidigeSpeler().Naam + " is aan de beurt.";
            }
            else
            {
                this.status = "U gooide " + this.worp + ". Verplaats een pion.";
            }
            if (!this.Log.LogOnly)
            {
                this.UpdateBord();
            }
        }

        public void PlaatsPion(int speler, int pion, bool move, bool pionMoetTerug, int vakNummer)
        {
            this.spelers[speler].Pionnen[pion].Move = move;
            this.spelers[speler].Pionnen[pion].PionMoetTerug = pionMoetTerug;
            this.Bord.PlaatsPion(this.spelers[speler].Pionnen[pion], vakNummer);
        }

        public bool heeftWinnaar()
        {
            for (int i = 0; i < this.spelers.Count(); i++)
            {
                if (this.spelers[i].isWinnaar())
                    return true;
            }
            return false;
        }

        public void Trace(string str)
        {
            this.log.trace(str);
        }

        // Get Huidige Speler
        public Speler getHuidigeSpeler()
        {
            return this.spelers[this.huidigeSpeler];
        }

        // Spelers Property
        public Speler[] Spelers
        {
            get { return spelers; }
            set { spelers = value; }
        }

        // Bord Property
        public Bord Bord
        {
            get { return bord; }
            set { bord = value; }
        }

        // HuidigeSpeler Property
        public int HuidigeSpeler
        {
            get { return huidigeSpeler; }
            set { huidigeSpeler = value; }
        }

        // Worp Property
        public int Worp
        {
            get { return worp; }
            set { worp = value; }
        }

        // Status Property
        public string Status
        {
            get { return status; }
            set { status = value; }
        }

        // Log Property
        public Log Log
        {
            get { return log; }
            set { log = value; }
        }
    }
}